home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / archival / ftp / BFTP.312 / bftp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-29  |  35.3 KB  |  1,572 lines

  1. /************************************************************************
  2.  *                                    *
  3.  *     Background File Transfer Program (BFTP)                *
  4.  *                                    *
  5.  *    Written at USC/Information Sciences Institute            *
  6.  *    September, 1988                            *
  7.  *                                    *
  8.  *      BFTP is Public Domain, and may be used for any purpose as    *
  9.  *      long as this notice is not removed.  USC-ISI does not assume    *
  10.  *    any responsibility for the correctness, performance, or use    *
  11.  *    of this software.                        *
  12.  *                                    *
  13.  ************************************************************************/
  14.  
  15. /*
  16.  *    bftp.c
  17.  *
  18.  *    The "bftp" tty-style user interface, is implemented in this module.
  19.  *    
  20. */
  21.  
  22. #include <stdio.h>
  23. #include <signal.h>
  24. #include <ctype.h>
  25. #include <errno.h>
  26. #include <sys/types.h>
  27. #include <sys/socket.h>
  28. #include <sys/param.h>
  29. #include <sys/file.h>
  30. #include <netinet/in.h>
  31.  
  32. #ifdef ISI4_2
  33. #include <netdb.h-bind>
  34. #else
  35. #include <netdb.h>
  36. #endif
  37.  
  38. #include <time.h>
  39. #include "bftp.h"
  40. #include "ucb_cp.h"
  41.  
  42. extern char
  43.     *get_request_file(),
  44.     *introduction,
  45.     *version,
  46.     *background;
  47. extern boolean
  48.     parse_date(),
  49.     read_req(),
  50.     write_req(),
  51.     queue_req(),
  52.     print_req();
  53. extern char
  54.     *expand_stru(),
  55.     *expand_mode(),
  56.     **get_save_files();
  57.  
  58. extern void 
  59.     format_time(),
  60.     close_listp(),
  61.     redisplay(),
  62.     unpack_filetype(),
  63.     init_user(),
  64.     init_req();
  65.  
  66. extern int
  67.       resolve_name();
  68.  
  69. extern char
  70.     bftp_dir[MAXPATHLEN],
  71.     def_user[20],
  72.     def_mailbox[101],
  73.     def_hostname[80];
  74.  
  75. extern struct hostinfo src, dst;
  76. extern struct fileinfo fil;
  77. extern struct reqinfo nullreq;
  78.    
  79. extern u_long start;
  80.  
  81. static struct reqinfo req;
  82. u_long    local_addr;
  83. int 
  84.     verbose = FALSE;
  85.     type = ASCII,    /* Ascii plus form, Ebcdic plus form,
  86.             (form = Non-print, Telnet, or Carriage-control)
  87.             Image, or Local plus Byte-size */
  88.     bytesiz = DEFAULT_BYTESZ,
  89.     form = NONPRINT;
  90.  
  91. int s, ns, len;                /* socket stuff */
  92. struct sockaddr_in sin, from;
  93.  
  94. #define p_prompt(str) if (str) printf("  %s ", str)
  95. #define p_help(str) if (str) printf("?%s\n", str)
  96.  
  97. char *help_preamble =
  98. "  Type 'help-all'       for description of commands\n\
  99.        'explain'        for detailed explanation\n\
  100.        'simple-example' for example using 'prompt'\n\n\
  101.   Commands may be abbreviated; arguments may appear on the command line.\n\
  102.   Type <control-C> to exit a command and display the BFTP prompt.\n\n";
  103.  
  104. char *explanation1 =
  105. "To have the BFTP program prompt you for file transfer parameters, such as\n\
  106. host names, logins, and file names, enter the 'prompt' command.  Use the\n\
  107. 'show' command to display the current request, and the 'init' command to\n\
  108. reset all of the parameters to their default values.\n\
  109. \n\
  110. The 'verify' command tells the BFTP server to connect to the specified hosts\n\
  111. (while you wait) to determine whether the parameters to be used in the\n\
  112. transfer are supported.  Use the 'submit' command to transfer the file in\n\
  113. background mode.  The 'transfer' command performs the file transfer while\n\
  114. you wait, rather than in the background.\n\
  115. \n\
  116. The 'find' command can be used to locate and display a request that is\n\
  117. waiting to be run.  Once a request is displayed, it can be changed and\n\
  118. resubmited, or cancelled.\n\
  119. \n\
  120. Commands may be abreviated, and arguments may be entered, separated by\n\
  121. spaces, on the command line.  For most fields, typing '?' <return> displays\n\
  122. a description of the argument that is to be entered.  Use <control-C> to\n\
  123. abort a command and return to the BFTP prompt, and use the 'quit' command\n\
  124. to exit the BFTP program.\n";
  125.       
  126. char *explanation2 = 
  127. "\n\
  128. The commands, 'r-list', 'r-load', 'r-store', and 'r-delete', are used to list\n\
  129. requests that have been stored in file, to read a file in as the current\n\
  130. request, to save a request in a file, and to delete a request file.\n\
  131. \n\
  132. The remainder of the commands are used to change individual parameters.\n\
  133. When one is submitting more than one file transfer request, these commands\n\
  134. can be used to change specific parameters, such as the source file name\n\
  135. (using 's-file') and the destination file name (using 'd-file').  This may\n\
  136. be easier than repeating the whole 'prompt' sequence.\n";
  137.  
  138. char *terminology =
  139. "\n\
  140. Additional BFTP terminology:\n\
  141.    The 'mailbox' is the address where the report on the outcome of the\n\
  142.        transfer will be sent.\n\
  143.    The 'request keyword' will be checked if you should want to find out\n\
  144.        the status of a request in the future, and/or cancel it.  The\n\
  145.        keyword is made up by the user and entered when the request is\n\
  146.        submitted.  It may be left blank if no checking is required.\n\
  147.    The 'multiple' flag specifies that the wildcard character '*' will be\n\
  148.        used to match multiple source file names.\n\
  149.    The 'append' flag specifies that the file should be appended to an\n\
  150.        existing file, rather than copied to a new file.\n\
  151.    The 'unique' flag specifies that the STOU command will be used to store\n\
  152.        the file.  If this command is supported by the receiving host, it\n\
  153.        will cause a unique file name to be created.\n\
  154.    The 'StartTime', entered when a file is submitted or via the 'time'\n\
  155.        command, is the time that the transfer will be attempted for the first\n\
  156.        time.  The 'interval' command sets how often the transfer will be\n\
  157.        retried (in minutes), and the maximum number of tries.  Each time that\n\
  158.        a transfer is retried, the retry interval will be doubled, up to a\n\
  159.        maximum of 4 hours.\n\
  160. ";
  161.  
  162. boolean
  163. get_cr()
  164. {
  165. l1: printf("\nType <CR> for more help; type <control-C> for BFTP prompt: ");
  166.    (void) gets(line);
  167.    makeargv();
  168.    if (margc && margv[0][0] == '?') {
  169.       printf("Type <CR> to confirm.\n");
  170.       goto l1;
  171.       }
  172.   if (margc)
  173.      return(FALSE);
  174.   else
  175.      return(TRUE);
  176. } /* get_cr */
  177.  
  178. boolean
  179. set_boolean(argc, argv, prompt, helpstr)
  180.    int argc;
  181.    char *argv[];
  182.    char *prompt, *helpstr;
  183. {
  184.    int len;
  185.    
  186.    if (argc < 1) {
  187. l1:   p_prompt(prompt);
  188.       (void) gets(line);
  189.       makeargv();
  190.       argc = margc;
  191.       argv = margv;
  192.       if (argc < 1) {
  193.      p_help(helpstr);
  194.      goto l1;
  195.          }
  196.       }
  197.  
  198.    len = strlen(argv[0]);
  199.    if (!strncmp(argv[0], "true", len?len:1))
  200.       return(TRUE);
  201.    else if (!strncmp(argv[0], "false", len?len:1))
  202.       return(FALSE);
  203.    else if (!strncmp(argv[0], "yes", len?len:1))
  204.       return(TRUE);
  205.    else if (!strncmp(argv[0], "no", len?len:1))
  206.       return(FALSE);
  207.    else {
  208.        p_help(helpstr);
  209.        goto l1;
  210.        }
  211. } /* set_boolean */
  212.  
  213. set_form(argc, argv, prompt, helpstr)
  214.    int argc;
  215.    char *argv[];
  216.    char *prompt, *helpstr;
  217. {
  218.    int len;
  219.    
  220.    if (argc < 1) {
  221. l1:   p_prompt(prompt);
  222.       (void) gets(line);
  223.       makeargv();
  224.       argc = margc;
  225.       argv = margv;
  226.       if (argc < 1) {
  227.      p_help(helpstr);
  228.      goto l1;
  229.          }
  230.       }
  231.  
  232.     len = strlen(argv[0]);
  233.     if (!strncmp(argv[0], "nonprint", len?len:1))
  234.        form = NONPRINT;
  235.     else if (!strncmp(argv[0], "telnet", len?len:1))
  236.        form = TELNET; 
  237.     else if (!strncmp(argv[0], "carriage-control", len?len:1))
  238.        form = CCNTRL; 
  239.     else {
  240.        p_help(helpstr);
  241.        goto l1;
  242.        }
  243. } /* set_form */
  244.  
  245. int
  246. set_host(argc, argv, prompt, helpstr, result)
  247.    int argc;
  248.    char *argv[];
  249.    char *prompt, *helpstr, *result;
  250. {
  251.    char temp[80];
  252.    u_long inaddr;
  253.  
  254.    if (argc < 1) {
  255. l1:   p_prompt(prompt);
  256.       (void) gets(line);
  257.       makeargv();
  258.       argc = margc;
  259.       argv = margv;
  260.       }
  261.    if (argc)
  262.       strcpy(temp, argv[0]);
  263.    else if (strlen(def_hostname))
  264.       strcpy(temp, def_hostname);
  265.    else {
  266.       p_help(helpstr);
  267.       goto l1;
  268.       }
  269.  
  270.    if (resolve_name(temp, &inaddr, 1)) {
  271.       if (result) strcpy(result, temp);
  272.       }
  273.    else {
  274.       p_help(helpstr);
  275.       goto l1;
  276.       }
  277. } /* set_host */
  278.  
  279. set_mbox(argc, argv, prompt, helpstr)
  280.    int argc;
  281.    char *argv[];
  282.    char *prompt, *helpstr;
  283. {
  284.    char temp[80], errorstr[40];
  285.  
  286.    if (argc < 1) {
  287. l1:   p_prompt(prompt);
  288.       (void) gets(line);
  289.       makeargv();
  290.       argc = margc;
  291.       argv = margv;
  292.       }
  293.    if (argc)
  294.       strcpy(temp, argv[0]);
  295.    else if (strlen(def_mailbox))
  296.       strcpy(temp, def_mailbox);
  297.    else {
  298.       p_help(helpstr);
  299.       goto l1;
  300.       }
  301.  
  302.    if (!mailbox_ok(temp, errorstr)) {
  303.       errorstr[strlen(errorstr)-1] = '\0';
  304.       p_help(errorstr);
  305.       p_help(helpstr);
  306.       goto l1;
  307.       }
  308.    else
  309.       strcpy(req.mailbox, temp);
  310. } /* set_mbox */
  311.  
  312. set_mode(argc, argv, prompt, helpstr)
  313.    int argc;
  314.    char *argv[];
  315.    char *prompt, *helpstr;
  316. {
  317.    int len;
  318.    
  319.    if (argc < 1) {
  320. l1:   p_prompt(prompt);
  321.       (void) gets(line);
  322.       makeargv();
  323.       argc = margc;
  324.       argv = margv;
  325.       if (argc < 1) {
  326.      p_help(helpstr);
  327.      goto l1;
  328.          }
  329.       }
  330.  
  331.    len = strlen(argv[0]);
  332.    if (!strncmp(argv[0], "stream", len?len:1))
  333.       fil.mode = 'S';
  334.    else if (!strncmp(argv[0], "block", len?len:1))
  335.       fil.mode = 'B';
  336.    else if (!strncmp(argv[0], "compressed", len?len:1))
  337.       fil.mode = 'C';
  338.    else {
  339.        p_help(helpstr);
  340.        goto l1;
  341.        }
  342. } /* set_mode */
  343.  
  344. int
  345. check_number(arg)
  346.    char *arg;
  347. {
  348.    int num;
  349.    char *cp;
  350.     
  351.    for (cp = arg; *cp; cp++) 
  352.       if (! isdigit(*cp))
  353.      return(-1);
  354.    num = atoi(arg);
  355.    return(num);
  356. } /* check_number */
  357.  
  358. set_number(argc, argv, prompt, helpstr, result)
  359.    int argc;
  360.    char *argv[];
  361.    char *prompt, *helpstr;
  362.    int *result;
  363. {
  364.    int temp;
  365.    
  366.    if (argc < 1) {
  367. l1:   p_prompt(prompt);
  368.       (void) gets(line);
  369.       makeargv();
  370.       argc = margc;
  371.       argv = margv;
  372.       if (argc < 1) {
  373.      p_help(helpstr);
  374.      goto l1;
  375.          }
  376.       }
  377.  
  378.    if ((temp = check_number(argv[0])) > 0)
  379.       *result = temp;
  380.    else {
  381.        p_help(helpstr);
  382.        goto l1;
  383.        }
  384. } /* set_number */
  385.  
  386. set_string(argc, argv, prompt, helpstr, result)
  387.    int argc;
  388.    char *argv[];
  389.    char *prompt, *helpstr, *result;
  390. {
  391.    if (argc < 1) {
  392. l1:   p_prompt(prompt);
  393.       (void) gets(line);
  394.       makeargv();
  395.       argc = margc;
  396.       argv = margv;
  397.       }
  398.    if (argc && argv[0][0] == '?') {
  399.       printf("Type <CR> to blank field.\n%s%s\n", 
  400.          (helpstr)?"?":NULLSTR, (helpstr)?helpstr:NULLSTR);
  401.       goto l1;
  402.       }
  403.  
  404.    if (result) strcpy(result, (argc)?argv[0]:NULLSTR);
  405. } /* set_string */
  406.  
  407. set_stru(argc, argv, prompt, helpstr)
  408.    int argc;
  409.    char *argv[];
  410.    char *prompt, *helpstr;
  411. {
  412.    int len;
  413.    
  414.    if (argc < 1) {
  415. l1:   p_prompt(prompt);
  416.       (void) gets(line);
  417.       makeargv();
  418.       argc = margc;
  419.       argv = margv;
  420.       if (argc < 1) {
  421.      p_help(helpstr);
  422.      goto l1;
  423.          }
  424.       }
  425.  
  426.    len = strlen(argv[0]);
  427.    if (!strncmp(argv[0], "file", len?len:1))
  428.       fil.stru = 'F';
  429.    else if (!strncmp(argv[0], "page", len?len:1))
  430.       fil.stru = 'P';
  431.    else if (!strncmp(argv[0], "record", len?len:1))
  432.       fil.stru = 'R';
  433.    else {
  434.        p_help(helpstr);
  435.        goto l1;
  436.        }
  437.  
  438.    if (fil.stru =='P') {
  439.       fil.mode = 'S';
  440.       strcpy(fil.filetype, "L 36");
  441.       printf("Setting mode = 'stream'; type = 'local 36'.\n");
  442.       }
  443. } /* set_stru */
  444.  
  445. set_time(argc, argv, prompt, helpstr, def)
  446.    int argc;
  447.    char *argv[];
  448.    char *prompt, *helpstr;
  449.    time_t def;
  450. {
  451.    int i;
  452.    time_t date;
  453.    char temp[80];
  454.  
  455.    if (argc > 0) {
  456.       /* reconstruct the command line */
  457.       temp[0] = '\0';
  458.       for (i = argc; i; i--) {
  459.      strcat(temp, argv[argc-i]);
  460.      strcat(temp, " ");
  461.          }
  462.       }
  463.    else {
  464. l1:   p_prompt(prompt);
  465.       (void) gets(line);
  466.       strcpy(temp, line);
  467.       makeargv();
  468.       argc = margc;
  469.       argv = margv;
  470.       }
  471.    if (argc && argv[0][0] == '?') {
  472.       p_help(helpstr);
  473.       goto l1;
  474.       }
  475.  
  476.    if (!strlen(temp))
  477.       start = (def > time(NULL))? def: 0;
  478.    else if (parse_date(temp, &date)) 
  479.      start = (date>time(NULL))? date: 0;
  480.       else {
  481.      p_help(helpstr);
  482.      goto l1;
  483.          }
  484. } /* set_time */
  485.  
  486. set_tmode(argc, argv, prompt, helpstr)
  487.    int argc;
  488.    char *argv[];
  489.    char *prompt, *helpstr;
  490. {
  491.    int len;
  492.    
  493.    if (argc < 1) {
  494. l1:   p_prompt(prompt);
  495.       (void) gets(line);
  496.       makeargv();
  497.       argc = margc;
  498.       argv = margv;
  499.       if (argc < 1) {
  500.      p_help(helpstr);
  501.      goto l1;
  502.          }
  503.       }
  504.  
  505.     len = strlen(argv[0]);
  506.     if (!strncmp(argv[0], "copy", len?len:1))
  507.        fil.reqtype = COPY;
  508.     else if (!strncmp(argv[0], "move", len?len:1))
  509.        fil.reqtype = MOVE; 
  510.     else if (!strncmp(argv[0], "delete", len?len:1))
  511.        fil.reqtype = DFILE; 
  512.     else {
  513.        p_help(helpstr);
  514.        goto l1;
  515.        }
  516. } /* set_tmode */
  517.  
  518. set_type(argc, argv, prompt, helpstr)
  519.    int argc;
  520.    char *argv[];
  521.    char *prompt, *helpstr;
  522. {
  523.    int len;
  524.    
  525.    if (argc < 1) {
  526. l1:   p_prompt(prompt);
  527.       (void) gets(line);
  528.       makeargv();
  529.       argc = margc;
  530.       argv = margv;
  531.       if (argc < 1) {
  532.      p_help(helpstr);
  533.      goto l1;
  534.          }
  535.       }
  536.  
  537.    len = strlen(argv[0]);
  538.    if (!strncmp(argv[0], "text", len?len:1)) {
  539.        type = ASCII;
  540.        form = NONPRINT;
  541.        strcpy(fil.filetype, "A N");
  542.        }
  543.    else if (!strncmp(argv[0], "ascii", len?len:1)) {
  544.        set_form(--argc, ++argv, 
  545.          "(nonprint/telnet/carriage-control)",
  546.          "File format (usually 'nonprint')");
  547.        type = ASCII;
  548.        sprintf(fil.filetype,"A %s",
  549.            (form==NONPRINT)?"N":(form==TELNET)?"T":"C");
  550.        }
  551.    else if (!strncmp(argv[0], "ebcdic", len?len:1)) {
  552.        set_form(--argc, ++argv, 
  553.          "(nonprint/telnet/carriage-control)",
  554.          "File format (usually 'nonprint')");
  555.        type = EBCDIC;
  556.        sprintf(fil.filetype,"E %s",
  557.            (form==NONPRINT)?"N":(form==TELNET)?"T":"C");
  558.        }
  559.    else if (!strncmp(argv[0], "local", len?len:1)) {
  560.        set_number(--argc, ++argv, 
  561.          "(byte size)",
  562.          "An integer byte size",
  563.           &bytesiz);
  564.        type = LOCAL;
  565.        sprintf(fil.filetype,"L %d",bytesiz);
  566.        }
  567.    else if (!strncmp(argv[0], "image", len?len:1) ||
  568.         !strncmp(argv[0], "binary", len?len:1)) {
  569.        type = IMAGE;
  570.        strcpy(fil.filetype,"I");
  571.        }
  572.    else {
  573.        p_help(helpstr);
  574.        goto l1;
  575.        }
  576. } /* set_type */
  577.  
  578. char *date_example =
  579.   "Date and/or time to start transfer, e.g. '4 July 2001 4:01pm'";
  580.  
  581. timecmd(argc, argv)
  582.    int argc;
  583.    char *argv[];
  584. {
  585.    set_time(--argc, ++argv,
  586.           "(start time -- <CR> means 'now')",
  587.       date_example,
  588.       0);
  589. }
  590.  
  591. interval(argc, argv)
  592.    int argc;
  593.    char *argv[];
  594. {
  595.    set_number(--argc, ++argv, 
  596.          "(starting value for minutes between tries)",
  597.          "An integer.",
  598.           &req.interval);
  599.    set_number(--argc, ++argv, 
  600.          "(maximum number of attempts)",
  601.          "An integer.",
  602.           &req.ntries);
  603.  
  604.    /* *** should interval and ntries be limited? */    
  605. } /* timecmd */
  606.  
  607. gethost(argc, argv)
  608.    int argc;
  609.    char *argv[];
  610. {    
  611.    boolean source = (argv[0][0] == 's');
  612.    char temp[80];
  613.    int len = strlen(def_hostname);
  614.  
  615.    sprintf(temp,"(host%s%s)",
  616.        (len)?" -- <CR> means ":NULLSTR,
  617.        (len)?def_hostname: NULLSTR);
  618.  
  619.    set_host(--argc, ++argv,
  620.         temp,
  621.         "Host name / dotted-decimal host number.",
  622.         (source)?src.host:dst.host);
  623. }
  624.  
  625. getuser(argc, argv)
  626.    int argc;
  627.    char *argv[];
  628. {
  629.    boolean source = (argv[0][0] == 's');
  630.  
  631.    set_string(--argc, ++argv,
  632.           "(login)",
  633.           "User name / login.",
  634.           (source)?src.user:dst.user);
  635.    strcpy((source)?src.passwd:dst.passwd, getpass(" ( password) "));
  636. }
  637.  
  638. explain(argc, argv)
  639.    int argc;
  640.    char *argv[];
  641. {
  642.    printf("%s%s",introduction, explanation1);
  643.    if (get_cr()) {
  644.       printf(explanation2);
  645.       if (get_cr()) {
  646.      printf(terminology);
  647.      if (get_cr())
  648.         printf(background);
  649.          }
  650.       }
  651. }
  652.  
  653. sExample(argc, argv)
  654.    int argc;
  655.    char *argv[];
  656. {
  657. char *seText1 = 
  658. "\nSimple example using the 'prompt' command:\n\n\
  659.     BFTP> prompt<CR>\n\
  660.       text/binary: t<CR>\n\n\
  661.       Source --\n\
  662.         Host: venera.isi.edu<CR>\n\
  663.         Login: anonymous<CR>\n\
  664.         Password: guest<CR>\t[BFTP does not echo!]\n\
  665.         Dir: pub/<CR>\n\
  666.         File:  sample-file.txt<CR>\n\n\
  667.       Destination --\n\
  668.         Host: hobgoblin.isi.edu<CR>\n\
  669.         Login: deschon<CR>\n\
  670.         Password: secret<CR>\t[BFTP does not echo!]\n\
  671.         Dir:<CR>\t\t[leave blank for home directory]\n\
  672.         File (blank if same as Source):<CR>\n\n\
  673.         [BFTP displays the request]\n\n\
  674. ";
  675. char *seText2 =
  676. "\n\
  677.     BFTP> verify<CR>\n\n\
  678.         [BFTP verifies that the parameters are correct]\n\n\
  679.     BFTP> submit<CR>\n\n\
  680.     Checking parameters...\n\n\
  681.       StartTime -- <CR> means 'now': 13:30<CR>\n\
  682.       RequestKeyword (optional): <CR>\n\n\
  683.     Request bftp637536643 submitted to run at Mar 15 13:30:43 1990 PST.\n\n\
  684.     BFTP>\n\n\
  685. [end of example]\n\n\
  686. ";
  687.  
  688.    printf(seText1);
  689.    if (get_cr())
  690.       printf(seText2);
  691. }
  692.  
  693. show()
  694. {
  695.     char temp[40];
  696.  
  697.     printf("\n");
  698.     print_req(stdout, &req, &src, &dst, &fil, TRUE);
  699.     
  700.     if (start) {
  701.     format_time(start, temp);
  702.     printf("    Start after %s.  Verbose mode = %s\n", 
  703.         temp, (verbose)? "ON": "OFF");
  704.     }
  705.     else
  706.        printf("    Start immediately.  Verbose mode = %s\n", 
  707.                (verbose)? "ON": "OFF");
  708. }
  709.  
  710. tmode(argc, argv)
  711.    int argc;
  712.    char *argv[];
  713. {
  714.    set_tmode(--argc, ++argv, 
  715.          "(copy/move/delete)",
  716.          "Transfer mode (usually 'copy')");
  717. }
  718.  
  719. compose()
  720. {
  721.    int len = strlen(def_hostname);
  722.    u_long addr;
  723.    char tmppass[MAXLEN];
  724.    struct hostinfo *xxx;
  725.    char temp[80];
  726.  
  727.    fil.reqtype = COPY;
  728.  
  729.    line[0] = '\0';
  730.    makeargv();
  731.    set_type(margc, margv, 
  732.         "text/binary:",
  733.         "File type (text = 'a n'; binary = image;\n\
  734. \t    ascii/ebcdic/image/local are also legal options)");
  735.  
  736.    for (xxx = &src; xxx ; xxx = (xxx == &src) ? &dst: NULL) {
  737.     printf("\n  %s --\n", (xxx == &src) ? "Source":"Destination");
  738.  
  739.     line[0] = '\0';
  740.     makeargv();
  741.     sprintf(temp,"Host name / dotted-decimal host number%s%s.",
  742.        (len)?"  / <CR> for ":NULLSTR,
  743.        (len)?def_hostname: NULLSTR);
  744.  
  745.     set_host(margc, margv,
  746.            "  Host:",
  747.            temp,
  748.            xxx->host);
  749.  
  750.     line[0] = '\0';
  751.     makeargv();
  752.     set_string(margc, margv,
  753.            "  Login:",
  754.            "User name / login.",
  755.            xxx->user);
  756.  
  757.     strcpy(xxx->passwd, getpass("    Password: "));
  758.  
  759.     line[0] = '\0';
  760.     makeargv();
  761.     set_string(margc, margv,
  762.        "  Dir:",
  763.        (xxx == &src)? "Directory where source file is located"
  764.                     : "Directory where destination file will be put",
  765.        xxx->dir);
  766.  
  767.     line[0] = '\0';
  768.     makeargv();
  769.     set_string(margc, margv,
  770.            (xxx == &src)? "  File:"
  771.                         : "  File (blank if same as Source):",
  772.            "File name",
  773.            xxx->file);
  774.         }
  775.  
  776.     show();
  777. } /* compose */
  778.  
  779. setapp(argc, argv)
  780.    int argc;
  781.    char *argv[];
  782. {
  783.    int ret;
  784.  
  785.    ret = set_boolean(--argc, ++argv,
  786.             "(true/false)",
  787.             "Append file to existing destination file?");
  788.  
  789.    if (ret) fil.creation = APPE;
  790.    else if (fil.creation != STOU) fil.creation = STOR;
  791. }
  792.  
  793. setuniq(argc, argv)
  794.    int argc;
  795.    char *argv[];
  796. {
  797.    int ret;
  798.  
  799.    ret = set_boolean(--argc, ++argv,
  800.             "(true/false)",
  801.             "Create unique file name using STOU command?");
  802.  
  803.    if (ret) fil.creation = STOU;
  804.    else if (fil.creation != APPE) fil.creation = STOR;
  805. }
  806.  
  807. setmult(argc, argv)
  808.    int argc;
  809.    char *argv[];
  810. {
  811.    fil.multflag = 
  812.      set_boolean(--argc, ++argv,
  813.          "(true/false)",
  814.          "Enable wildcard matching?");
  815.    if (fil.multflag) printf(
  816.       "\nUse the VERIFY command to verify that your file list is correct!\n\n");
  817. }
  818.  
  819. setverbose(argc, argv)
  820.    int argc;
  821.    char *argv[];
  822. {
  823.    verbose = 
  824.      set_boolean(--argc, ++argv,
  825.          "(true/false)",
  826.          "Display FTP commands on verify and transfer commands?");
  827. }
  828.  
  829. fstru(argc, argv)
  830.    int argc;
  831.    char *argv[];
  832. {
  833.    set_stru(--argc, ++argv, 
  834.         "(file/record/page)",
  835.        "Structure (usually 'file')");
  836. }
  837.  
  838. ftype(argc, argv)
  839.    int argc;
  840.    char *argv[];
  841. {
  842.    set_type(--argc, ++argv, 
  843.        "(text/binary or ascii/ebcdic/image/local)",
  844.        "File type (text = 'a n'; binary = image;\n\
  845. \t    ascii/ebcdic/image/local are also legal options)");
  846. } /* ftype */
  847.  
  848. mode(argc, argv)
  849.    int argc;
  850.    char *argv[];
  851. {
  852.    set_mode(--argc, ++argv, 
  853.        "(stream/block/compress)",
  854.        "Mode (usually 'stream')");
  855. } /* mode */
  856.  
  857. quit()
  858. {
  859.   printf("Bye\n");
  860.   exit(0);
  861. }
  862.  
  863. dir(argc, argv)
  864.    int argc;
  865.    char *argv[];
  866. {
  867.    boolean source = (argv[0][0] == 's');
  868.  
  869.    set_string(--argc, ++argv,
  870.           "(directory)",
  871.           (source)? "Directory where source file is located"
  872.                   : "Directory where destination file will be put",
  873.           (source)? src.dir: dst.dir);
  874. }
  875.  
  876. file(argc, argv)
  877.    int argc;
  878.    char *argv[];
  879. {
  880.    boolean source = (argv[0][0] == 's');
  881.  
  882.    set_string(--argc, ++argv,
  883.           "(file name)",
  884.           (source)? "Source file name"
  885.                   : "Destination file name",
  886.           (source)? src.file: dst.file);
  887. }
  888.  
  889. passwd(argc, argv)
  890.    int argc;
  891.    char *argv[];
  892. {
  893.    boolean source = (argv[0][0] == 's');
  894.  
  895.    strcpy((source)?src.passwd:dst.passwd, getpass("  Enter password: "));
  896. }
  897.  
  898. acct(argc, argv)
  899.    int argc;
  900.    char *argv[];
  901. {
  902.    boolean source = (argv[0][0] == 's');
  903.    
  904.    set_string(--argc, ++argv,
  905.           "(acct)",
  906.           "Account string for this login",
  907.           (source)?src.acct:dst.acct);
  908. }
  909.  
  910. port(argc, argv)
  911.    int argc;
  912.    char *argv[];
  913. {
  914.    int port;
  915.    boolean source = (argv[0][0] == 's');
  916.  
  917.    set_number(--argc, ++argv,
  918.         "(port)",
  919.         "Port number (usually 21)",
  920.         &port);
  921.    if (port > 0xffff)
  922.       printf("?Illegal port number: %d\n", port);
  923.    else
  924.       if (source)
  925.      src.port = port;
  926.       else
  927.      dst.port = port;
  928. }
  929.  
  930. int
  931. finderrors()
  932. {
  933.    u_long addr;
  934.    int count = 0;
  935.     
  936.    printf("\nChecking parameters...\n\n");
  937.  
  938.    if (!resolve_name(src.host, &addr, 1)) {
  939.       printf("Illegal source host number.\n");
  940.       count++;
  941.       }
  942.    if (!strlen(src.user)) {
  943.       printf("Source user name must be specified.\n");
  944.       count++;
  945.       }
  946.    if (!strlen(src.file)) {
  947.       printf("Source file name must be specified.\n");
  948.       count++;
  949.       }
  950.       
  951.    if (fil.reqtype != DFILE) {      
  952.       if (!resolve_name(dst.host, &addr, 1)) {
  953.      printf("Illegal destination host number.\n");
  954.      count++;
  955.      }
  956.       if (!strlen(dst.user)) {
  957.          printf("Destination user name must be specified.\n");
  958.          count++;
  959.          }
  960.  
  961.       /* check the destination file name */
  962.       if (fil.multflag) {
  963.          if ((fil.creation != APPE) && (!empty_str(dst.file)))
  964.          printf("Warning: destination file name will be ignored.\n");
  965.          }
  966.       else
  967.      if ((fil.reqtype != DFILE) && empty_str(dst.file)) {
  968.             printf("Destination file name must be specified.\n");
  969.         count++;
  970.         }
  971.       }
  972.  
  973.    /* check for source directory on mult */
  974.    if (fil.multflag && 
  975.        (fil.reqtype != DFILE) && (!strlen(src.dir)) && !strlen(dst.file)) {
  976.       printf(
  977.   "Warning: For multiple file transfer, a source directory may be required.\n");
  978.       line[0] = '\0';
  979.       makeargv();
  980.       if (!count) {
  981.      set_string(margc, margv,
  982.             "Directory:",
  983.             "Directory where source file is located",
  984.             src.dir);
  985.      }
  986.       }
  987.    
  988.    return(count);
  989. } /* finderrors */
  990.  
  991. verify(argc, argv)
  992.    int argc;
  993.    char *argv[];
  994. {
  995.    int save_mode,
  996.        filelen = strlen(dst.file);
  997.  
  998.    if (!filelen)
  999.       strcpy(dst.file, src.file);
  1000.    if (!finderrors()) {
  1001.       save_mode = fil.reqtype;
  1002.       fil.reqtype = (save_mode == DFILE)? VERIFY_SRC : VERIFY;
  1003.       submit_req(TRUE);
  1004.       fil.reqtype = save_mode;
  1005.       }
  1006.    if (!filelen)
  1007.       dst.file[0] = '\0';
  1008. }
  1009.  
  1010. transfernow(argc, argv)
  1011.    int argc;
  1012.    char *argv[];
  1013. {
  1014.    int filelen = strlen(dst.file);
  1015.  
  1016.    if (!filelen)
  1017.       strcpy(dst.file, src.file);
  1018.    if (!finderrors())
  1019.       submit_req(TRUE);
  1020.    if (!filelen)
  1021.       dst.file[0] = '\0';
  1022. }
  1023.  
  1024. mailbox(argc, argv)
  1025.    int argc;
  1026.    char *argv[];
  1027. {
  1028.    char temp[80];
  1029.    int len = strlen(def_mailbox);
  1030.  
  1031.    sprintf(temp,"(mailbox%s%s)",
  1032.        (len)?" -- <CR> means ":NULLSTR,
  1033.        (len)?def_mailbox: NULLSTR);
  1034.        
  1035.    set_mbox(--argc, ++argv,
  1036.         temp,
  1037.         "Mailbox to which results will be returned");
  1038. }
  1039.  
  1040. submit(argc, argv)
  1041.    int argc;
  1042.    char *argv[];
  1043. {
  1044.    char timestr[40], prompt[80];
  1045.    char temp[80];
  1046.    int len = strlen(def_mailbox);
  1047.  
  1048.    int filelen = strlen(dst.file);
  1049.    if (!filelen)
  1050.       strcpy(dst.file, src.file);
  1051.    if (!finderrors()) {
  1052.       if (start)
  1053.      format_time(start, timestr);
  1054.       else
  1055.      strcpy(timestr, "now");
  1056.       sprintf(prompt, "StartTime -- <CR> means '%s':", timestr);
  1057.       set_time(--argc, ++argv,
  1058.            prompt,
  1059.            date_example,
  1060.            start);
  1061.  
  1062.       if (!strlen(req.mailbox)) {
  1063.      line[0] = '\0';
  1064.      makeargv();
  1065.      sprintf(temp,"ReturnMailbox%s%s:",
  1066.          (len)?" -- <CR> means ":NULLSTR,
  1067.          (len)?def_mailbox:NULLSTR);
  1068.      set_mbox(margc, margv,
  1069.           temp,
  1070.           "Mailbox to which results will be returned");
  1071.          }
  1072.       
  1073.       strcpy(req.rpasswd, getpass("  RequestKeyword (optional): "));
  1074.    
  1075.       submit_req(FALSE);
  1076.       }
  1077.    if (!filelen)
  1078.       dst.file[0] = '\0';
  1079. }
  1080.  
  1081. submit_req(realtime)
  1082.    int realtime;
  1083. {
  1084.    FILE *xxx;
  1085.    char temp[MAXPATHLEN], path[MAXPATHLEN];
  1086.    u_long now;
  1087.  
  1088.    now = time(NULL);
  1089.    sprintf(path,"%s%d",REQPREFIX,now);
  1090.    
  1091.    sprintf(temp, "%s.req", path);
  1092.    if (realtime) {
  1093.       write_req(temp,&nullreq,&src,&dst,&fil,NULL);
  1094.       sprintf(temp, "%s %s%s.req\n", FXPATH, (verbose)?"-v ":NULLSTR, path);
  1095.       printf(temp);
  1096.       system(temp); 
  1097.       }
  1098.    else {
  1099.       sprintf(req.mailfile,"%s.msg",path);
  1100.       sprintf(req.cmdfile,"%s.cmd",path);
  1101.       write_req(temp,&req,&src,&dst,&fil,NULL);
  1102.       
  1103.       sprintf(temp, "%s.cmd", path);
  1104.       xxx = fdopen(open(temp,(O_WRONLY|O_CREAT),0600),"w");
  1105.       fprintf(xxx, "%s -v %s.req\n", FXPATH, path);
  1106.       fclose(xxx);
  1107.    
  1108.       sprintf(temp, "%s.msg", path);
  1109.       xxx = fdopen(open(temp,(O_WRONLY|O_CREAT),0600),"w");
  1110.       queue_req(&req, (now > start) ? now : start, temp);
  1111.       print_req(xxx, &req, &src, &dst, &fil, FALSE);
  1112.       fprintf(xxx,"\n%s\n",temp);
  1113.       fclose(xxx);
  1114.       printf("\n%s\n\n",temp);
  1115.       }
  1116. }
  1117.  
  1118. /* Find and change/cancel a request */
  1119.  
  1120. summarize(req)
  1121.    struct reqinfo *req;
  1122. {
  1123.    char temp[150];
  1124.  
  1125.    if (strlen(req->mailfile)) {
  1126.       printf("History:\n\n");
  1127.       sprintf(temp,"egrep 'submitted|starting|completed' %s\n",req->mailfile);
  1128.       system(temp);
  1129.       printf("\n");
  1130.       }
  1131.    else
  1132.       printf("History: No mail file found!\n\n");
  1133. }
  1134.  
  1135. boolean
  1136. ask(cp)
  1137.    char *cp;
  1138. {
  1139.    char temp[40];
  1140.  
  1141.    sprintf(temp, "Do you wish to %s this request?", cp);
  1142.    line[0] = '\0';
  1143.    makeargv();
  1144.    return(set_boolean(margc, margv,
  1145.               temp,
  1146.               "Answer 'yes' or 'no'.")
  1147.       );
  1148. }
  1149.  
  1150. char *cancel_text = "\n Previous request cancelled.\n";
  1151.  
  1152. find(argc, argv)
  1153.    int argc;
  1154.    char *argv[];
  1155. {
  1156.    char password[MAXLEN], temp[MAXLEN], request[20], id [20];
  1157.    char filename[MAXPATHLEN], listfile[MAXPATHLEN], *filep;
  1158.    u_long now;
  1159.    boolean found;
  1160.    int tmp;
  1161.    struct hostinfo tmpsrc, tmpdst;
  1162.    struct fileinfo tmpfil;
  1163.    struct reqinfo tmpreq;
  1164.  
  1165.    line[0] = '\0';
  1166.    makeargv();
  1167.    set_string(margc, margv,
  1168.           "RequestID (optional):",
  1169.           "Request id, for example 'bftp123456789'.",
  1170.           request);
  1171.  
  1172.    if (strlen(request)) {
  1173.       sprintf(filename,"%s.req",request);
  1174.       if (! read_req(filename, &tmpreq, &tmpsrc, &tmpdst, &tmpfil, listfile)) {
  1175.          printf("\nRequest %s not found.\n",request);
  1176.      return;
  1177.          }
  1178.       }
  1179.  
  1180.    strcpy(password, getpass("  RequestKeyword: "));
  1181.  
  1182.    if (strlen(request))
  1183.       filep = filename;
  1184.    else 
  1185.       filep = get_request_file(password);
  1186.    
  1187.    while (filep) {
  1188.       if ((read_req(filep, &tmpreq, &tmpsrc, &tmpdst, &tmpfil, listfile)) &&
  1189.           (strcmp(password, tmpreq.rpasswd) == 0)) {
  1190.      get_id(id, filep);
  1191.      printf("\nRequest: %s\n\n",id);
  1192.      print_req(stdout, &tmpreq, &tmpsrc, &tmpdst, &tmpfil, FALSE);
  1193.      summarize(&tmpreq);
  1194.          
  1195.      found = request_queued(filep);
  1196.      printf("\nYour request is %scurrently queued.\n",
  1197.         (found)?NULLSTR:"NOT ");
  1198.      
  1199.      if (ask("change")) {
  1200.         printf("\n Reading %s%s...\n",bftp_dir,filep);
  1201.         if (! read_req(filep,&req,&src,&dst,&fil,listfile))
  1202.            printf("\n Request file not found.\n");
  1203.         else {
  1204.            cancel_msg(filep, &tmpreq, tmpsrc.file, listfile);
  1205.            printf(cancel_text);
  1206.            unpack_filetype(fil.filetype,&type, &form, &bytesiz);
  1207.            show();
  1208.            printf("\nUse the 'submit' command to submit a new request.\n");
  1209.            close_listp();
  1210.            break;
  1211.            }
  1212.         }
  1213.      else
  1214.         if (ask("cancel")) {
  1215.            cancel_msg(filep, &tmpreq, tmpsrc.file, listfile);
  1216.            printf(cancel_text);
  1217.            }
  1218.      }
  1219.       if (strlen(request))
  1220.          break;
  1221.       else 
  1222.          filep = get_request_file(password);
  1223.       }
  1224. } /* find */
  1225.  
  1226. /* Request file management routines */
  1227.  
  1228. boolean
  1229. reqname(argc, argv, nptr)
  1230.    int argc;
  1231.    char *argv[];
  1232.    char *nptr;
  1233. {
  1234.    char temp[40], *cp;
  1235.  
  1236.    if (!strlen(def_user)) {
  1237.       printf(
  1238.      "\n\tSorry, you must be logged in for temporary request storage.\n\n");
  1239.       return(FALSE);
  1240.       }
  1241.    set_string(--argc, ++argv,
  1242.           "(request name)",
  1243.           NULL,
  1244.           temp);
  1245.  
  1246.    for (cp = temp; *cp && (*cp=='.' || *cp=='-' || isalnum(*cp)); cp++);
  1247.    if (*cp) {
  1248.       printf("\n?Alpha-numeric characters only please: %s\n",temp);
  1249.       return(FALSE);
  1250.       }
  1251.    else {
  1252.       sprintf(nptr, "%s.%s", SAVEPREFIX, temp);
  1253.       return(TRUE);
  1254.       }
  1255. } /* reqname */
  1256.  
  1257. delfile(argc, argv)
  1258.    int argc;
  1259.    char *argv[];
  1260. {
  1261.    char rname[MAXLEN], temp[MAXLEN];
  1262.  
  1263.    if (reqname(argc, argv, rname)) {
  1264.       printf("\n Deleting...%s\n", rname);
  1265.       sprintf(temp, "rm %s", rname);
  1266.       system(temp);
  1267.       }
  1268. }
  1269.  
  1270. getfile(argc, argv)
  1271.    int argc;
  1272.    char *argv[];
  1273. {
  1274.    char temp[MAXLEN], listfile[MAXLEN];
  1275.  
  1276.    if (reqname(argc, argv, temp)) {
  1277.       printf("\n Reading %s%s...\n",bftp_dir, temp);
  1278.       if (! read_req(temp,&req,&src,&dst,&fil,listfile))
  1279.          printf("\n Request file not found.\n");
  1280.       else {
  1281.          unpack_filetype(fil.filetype,&type, &form, &bytesiz);
  1282.          show();
  1283.      }
  1284.       }
  1285. }
  1286.  
  1287. savefile(argc, argv)
  1288.    int argc;
  1289.    char *argv[];
  1290. {
  1291.    char temp[MAXLEN];
  1292.  
  1293.    if (reqname(argc, argv, temp)) {
  1294.       printf("\n File name = %s%s\n",bftp_dir, temp);
  1295.       write_req(temp,&req,&src,&dst,&fil,NULL);
  1296.       }
  1297. }
  1298.  
  1299. listsavef()
  1300. {
  1301.    char **list, **temp;
  1302.    int i, maxlen = 0, linelen = 80;
  1303.     
  1304.    if (!strlen(def_user))
  1305.       printf(
  1306.    "\n\tSorry, you must be logged in for temporary request storage.\n\n");
  1307.    else {
  1308.       list = get_save_files();
  1309.       temp = list;
  1310.       while (*temp)
  1311.     if ((i = strlen(*temp++)) > maxlen) maxlen = i;
  1312.  
  1313.       maxlen += 4;
  1314.       while (*list) {
  1315.     if ((linelen+maxlen) > 80) {
  1316.        linelen = 2;
  1317.        printf("\n  ");
  1318.        };
  1319.     printf("%-*s", maxlen, *list++);
  1320.     linelen += maxlen;
  1321.         }
  1322.       printf("\n\n");
  1323.       }
  1324. } /* listsavef */
  1325.  
  1326. init()
  1327. {
  1328.     resolve_name(def_hostname, &local_addr, 1);
  1329.  
  1330.     strcpy(src.dir, NULLSTR);
  1331.     strcpy(src.file, NULLSTR);
  1332.     strcpy(src.host, NULLSTR);
  1333.     strcpy(src.user, NULLSTR);
  1334.     strcpy(src.passwd, NULLSTR);
  1335.     strcpy(src.acct, NULLSTR);
  1336.     src.port = DEFAULT_PORT;
  1337.     strcpy(dst.dir, NULLSTR);
  1338.     strcpy(dst.file, NULLSTR);
  1339.     strcpy(dst.host, NULLSTR);
  1340.     strcpy(dst.user, NULLSTR);
  1341.     strcpy(dst.passwd, NULLSTR);
  1342.     strcpy(dst.acct, NULLSTR);
  1343.     dst.port = DEFAULT_PORT;
  1344.     
  1345.     init_req(&req);
  1346.     strcpy(req.mailbox, NULLSTR); 
  1347.             /* make the user enter it, at least the first time */
  1348.     
  1349.     fil.reqtype = COPY;
  1350.     fil.stru = 'F';
  1351.     type = ASCII;
  1352.     bytesiz = DEFAULT_BYTESZ;
  1353.     form = NONPRINT;
  1354.     strcpy(fil.filetype,"A N");
  1355.     fil.mode = 'S';
  1356.     start = 0;
  1357.     fil.creation = STOR;
  1358.     fil.multflag = FALSE;
  1359. } /* init */
  1360.  
  1361. /* Command table for BFTP */
  1362.  
  1363. extern int help();
  1364. int helpall();
  1365.  
  1366. struct cmd cmdtab[] = {
  1367.     { "help",
  1368.         "List the commands ('help'), or print a description\n\
  1369. \t    (e.g. 'help prompt').",
  1370.         help },
  1371.     { "help-all",
  1372.         "Display a description of each command.",
  1373.         helpall },
  1374.     { "explain",
  1375.         "Display a detailed explanation of how to use this program.",
  1376.         explain },
  1377.     { "simple-example",
  1378.         "Display an example of how to enter and submit a request.",
  1379.         sExample },
  1380.  
  1381.     { "prompt",
  1382.         "Prompt for commonly-used parameters.",
  1383.         compose },
  1384.     { "show",
  1385.         "Display current parameter values.",
  1386.         show },
  1387.     { "init",
  1388.         "Return all parameters to their default values.",
  1389.         init },
  1390.  
  1391.     { "submit",
  1392.         "Submit the current request for background FTP.",
  1393.         submit },
  1394.     { "find",
  1395.         "Find and display a previous request (or cancel it).",
  1396.         find },
  1397.     { "transfer", 
  1398.         "Perform the current request in the foreground.",
  1399.         transfernow },
  1400.     { "verify", 
  1401.         "Make the connections now to check parameters.",
  1402.         verify },
  1403.     { "quit",
  1404.         "Exit the BFTP program.",
  1405.         quit },
  1406.  
  1407.     { "command",
  1408.         "Set the transfer mode.\n\
  1409. \t    copy:   Source file is copied to the destination file name.\n\
  1410. \t    move:   Source file is deleted after it has been copied.\n\
  1411. \t    delete: Source file is deleted.",
  1412.             tmode },
  1413.     { "mailbox",
  1414.         "Set the mailbox to which the results will be returned.",
  1415.         mailbox },
  1416.     { "verbose",
  1417.         "Set to true to show FTP commands on 'verify' & 'transfer'.",
  1418.         setverbose },
  1419.     { "time",
  1420.         "Date and/or time to start transfer.",
  1421.         timecmd },
  1422.     { "interval",
  1423.         "Starting retry interval in minutes, and number of tries.",
  1424.         interval },
  1425.  
  1426.     { "r-list",
  1427.         "List all bftp-save files.",
  1428.         listsavef },
  1429.     { "r-load",
  1430.         "Read a request file in as the current request.",
  1431.         getfile },
  1432.     { "r-store",
  1433.         "Save the current request in a file named 'bftp-save.name'.",
  1434.         savefile },
  1435.     { "r-delete",
  1436.         "Delete request file 'bftp-save.name'.",
  1437.         delfile },
  1438.  
  1439.     { "mode",
  1440.         "Set FTP mode to stream, block, or compress.",
  1441.         mode },
  1442.     { "stru",
  1443.         "Set FTP structure to file, record, or page.",
  1444.         fstru },
  1445.     { "type",
  1446.         "Set FTP type (ascii/ebcdic/image/local) & format/byte size.",
  1447.         ftype },
  1448.     { "multiple",
  1449.         "Set to true to transfer multiple files.",
  1450.         setmult },
  1451.     { "unique",
  1452.         "Set to true for unique file names (via the STOU command).",
  1453.         setuniq },
  1454.     { "append",
  1455.         "Set to true to append to destination file.",
  1456.         setapp },
  1457.  
  1458.     { "s-host",
  1459.         "Set the source host.",
  1460.         gethost },
  1461.     { "s-user",
  1462.         "Set the source login and password.",
  1463.         getuser },
  1464.         { "s-password",
  1465.         "Set the source password.",
  1466.         passwd },
  1467.     { "s-acct",
  1468.         "Set the account for the source login.",
  1469.         acct },
  1470.     { "s-dir", 
  1471.         "Set the source directory.",  
  1472.         dir },
  1473.     { "s-file", 
  1474.         "Set the source file name.", 
  1475.         file },
  1476.     { "s-port",
  1477.         "Set the port for the source FTP connection.",
  1478.         port },
  1479.  
  1480.     { "d-host",
  1481.         "Set the destination host.",
  1482.         gethost },
  1483.     { "d-user",
  1484.         "Set the destination login and password.",
  1485.         getuser },
  1486.         { "d-password",
  1487.         "Set the destination password.",
  1488.         passwd },
  1489.     { "d-acct",
  1490.         "Set the account for the destination login.",
  1491.         acct },
  1492.     { "d-dir",
  1493.         "Set the destination directory.",
  1494.         dir },
  1495.     { "d-file",
  1496.         "Set the destination file name.",
  1497.         file },
  1498.     { "d-port",
  1499.         "Set the port for the destination FTP connection.",
  1500.         port },
  1501.     { 0 },
  1502. };
  1503.  
  1504. int    NCMDS = (sizeof (cmdtab) / sizeof (cmdtab[0])) - 1;
  1505.  
  1506. helpall()
  1507. {
  1508.    register char *p;
  1509.    register struct cmd *c;
  1510.  
  1511.    for (c = cmdtab; p = c->c_name; c++) {
  1512.       /* Print section divider */
  1513.       if (!strcmp(c->c_name, "s-host")) {
  1514.      if (!get_cr())
  1515.         break;
  1516.      printf("\nSet source parameter:\n\n");
  1517.      }
  1518.       else if (!strcmp(c->c_name, "d-host")) {
  1519. /*     if (!get_cr())
  1520.         break;
  1521. */     printf("\nSet destination parameter:\n\n");
  1522.      }
  1523.       else if (!strcmp(c->c_name, "command")) {
  1524. /*     if (!get_cr())
  1525.         break;
  1526. */     printf("\nSet internal BFTP parameter:\n\n");
  1527.      }
  1528.       else if (!strcmp(c->c_name, "mode")) {
  1529. /*     if (!get_cr())
  1530.         break;
  1531. */     printf("\nSet FTP file parameter:\n\n");
  1532.      }
  1533.       else if (!strcmp(c->c_name, "r-list")) {
  1534.      if (!get_cr())
  1535.         break;
  1536.      printf("\nManage request files:\n\n");
  1537.      }
  1538.  
  1539.       /* Print help info */
  1540.       printf("  %-*s %s\n", HELPINDENT,
  1541.          c->c_name, c->c_help);
  1542.       }
  1543. }
  1544.  
  1545. main(argc,argv)
  1546.     int argc;
  1547.     char *argv[];
  1548. {
  1549.     register char *cp;
  1550.     int ret;
  1551.  
  1552.     argc--, argv++;
  1553.     while (argc > 0 && **argv == '-') {
  1554.     for (cp = *argv + 1; *cp; cp++)
  1555.         switch (*cp) {
  1556.             
  1557.         default:
  1558.            fprintf(stderr, "bftp: %c: unknown option\n", *cp);
  1559.            exit(1);
  1560.             }
  1561.         argc--, argv++;
  1562.     }
  1563.  
  1564.    init_user();
  1565.    init();
  1566.  
  1567.    printf("\n%s %s\n\n%s\n",
  1568.            "Background File Transfer:", version, 
  1569.         "For help type 'help' or '?'.\n");
  1570.    do_main();
  1571. } /* main */
  1572.